/**
 * @file power_off_charging.c
 *
 */

/*********************
*      INCLUDES
*********************/
#include "lv_watch.h"

#if USE_LV_WATCH_POWER_OFF_CHARGING != 0

#include <stdio.h>

/*********************
*      DEFINES
*********************/

/**********************
*      TYPEDEFS
**********************/

/**********************
*  STATIC PROTOTYPES
**********************/
static void power_off_charging_battery_task(lv_task_t * task);
static void power_off_charging_status_change(void * para);
static void power_off_charging_prepare_destory(lv_obj_t * activity_obj);
static uint8_t power_off_charging_get_img_index(uint8_t bat_sta);
static void power_off_charging_check_full(uint8_t * value);

/**********************
*  STATIC VARIABLES
**********************/

/**********************
*      MACROS
**********************/
#define POWER_OFF_CHARGING_LEVEL_1 25
#define POWER_OFF_CHARGING_LEVEL_2 50
#define POWER_OFF_CHARGING_LEVEL_3 75
#define POWER_OFF_CHARGING_LEVEL_4 100
#define POWER_OFF_CHARGING_LEVEL_MAX 4
#define POWER_OFF_CHARGING_FULL_CNT_MAX 5
/**********************
 *   GLOBAL FUNCTIONS
 ***********************/
lv_obj_t * power_off_charging_create(lv_obj_t * activity_obj)
{
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId           = ACT_ID_POWER_OFF_CHARGING;
        activity_ext.create          = power_off_charging_create;
        activity_ext.prepare_destory = power_off_charging_prepare_destory;
        activity_obj                 = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(activity_obj == NULL) {
            return(NULL);
        }
    }

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(obj == NULL) return NULL;
    lv_watch_obj_set_anim_mode(obj, LV_WATCH_ANIM_NO);

    lv_obj_t * img = lv_obj_get_child(activity_obj, NULL);
    if(WATCH_HAS_WALLPAPER) {
        if(img) {
            lv_img_set_src(img, ICON_BACKGROUND);
        }
    }

    lv_power_off_charging_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_power_off_charging_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    ext->battery_task = NULL;
    ext->bat_img_list[0] = NULL;
    ext->bat_img_list[1] = NULL;
    ext->bat_img_list[2] = NULL;
    ext->bat_img_list[3] = NULL;
    ext->display_index = 0;
    ext->ril_check_task = NULL;

    uint8_t bat = Hal_Battery_Get_Status();
    power_off_charging_check_full(&bat);

    if(100 > bat) {
        lv_obj_t * img_battery_0 = lv_img_create(obj, NULL);
        lv_obj_set_size(img_battery_0, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_battery_0, &ICON_POWER_OFF_CHARGING_0);

        lv_obj_t * img_battery_1 = lv_img_create(obj, NULL);
        ext->bat_img_list[0] = img_battery_1;
        lv_obj_set_size(img_battery_1, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_battery_1, &ICON_POWER_OFF_CHARGING_1);
        if(POWER_OFF_CHARGING_LEVEL_1 > bat) lv_obj_set_hidden(img_battery_1, true);

        lv_obj_t * img_battery_2 = lv_img_create(obj, NULL);
        ext->bat_img_list[1] = img_battery_2;
        lv_obj_set_size(img_battery_2, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_battery_2, &ICON_POWER_OFF_CHARGING_2);
        if(POWER_OFF_CHARGING_LEVEL_2 > bat) lv_obj_set_hidden(img_battery_2, true);

        lv_obj_t * img_battery_3 = lv_img_create(obj, NULL);
        ext->bat_img_list[2] = img_battery_3;
        lv_obj_set_size(img_battery_3, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_battery_3, &ICON_POWER_OFF_CHARGING_3);
        if(POWER_OFF_CHARGING_LEVEL_3 > bat) lv_obj_set_hidden(img_battery_3, true);

        lv_obj_t * img_battery_4 = lv_img_create(obj, NULL);
        ext->bat_img_list[3] = img_battery_4;
        lv_obj_set_size(img_battery_4, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_battery_4, &ICON_POWER_OFF_CHARGING_4);
        if(POWER_OFF_CHARGING_LEVEL_4 > bat) lv_obj_set_hidden(img_battery_4, true);

        lv_obj_t * img_power = lv_img_create(obj, NULL);
        lv_obj_set_size(img_power, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_power, &ICON_POWER_OFF_CHARGING_POWER);

        lv_obj_align(img_power, NULL, LV_ALIGN_CENTER, 0, 0);
        lv_obj_align(img_battery_0, NULL, LV_ALIGN_CENTER, 0, 0);
        lv_obj_align(img_battery_1, NULL, LV_ALIGN_CENTER, 0, 0);
        lv_obj_align(img_battery_2, NULL, LV_ALIGN_CENTER, 0, 0);
        lv_obj_align(img_battery_3, NULL, LV_ALIGN_CENTER, 0, 0);
        lv_obj_align(img_battery_4, NULL, LV_ALIGN_CENTER, 0, 0);

        ext->display_index = power_off_charging_get_img_index(bat);
        ext->battery_task = lv_task_create(power_off_charging_battery_task, 800, LV_TASK_PRIO_MID, NULL);
    } else {
        lv_obj_t * img_ok = lv_img_create(obj, NULL);
        lv_obj_set_size(img_ok, lv_obj_get_width(obj), lv_obj_get_height(obj));
        lv_img_set_src(img_ok, &ICON_POWER_OFF_CHARGING_OK);
        ext->battery_task = NULL;
    }

    Hal_Register_Charger_Status_Ind(power_off_charging_status_change);

    return(activity_obj);
}

/**********************
*   STATIC FUNCTIONS
**********************/
static lv_power_off_charging_ext_t * power_off_charging_get_ext(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_POWER_OFF_CHARGING);
    lv_obj_t * watch_obj = NULL;

    if(activity_obj) {
        lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    }


    if(watch_obj) {
        lv_power_off_charging_ext_t * ext = lv_obj_get_ext_attr(watch_obj);
        return ext;
    }
    return NULL;
}

static lv_obj_t * power_off_charging_get_obj(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_POWER_OFF_CHARGING);
    lv_obj_t * watch_obj = NULL;

    if(activity_obj) {
        lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    }

    return watch_obj;
}

static uint8_t power_off_charging_get_img_index(uint8_t bat_sta)
{
    if(bat_sta < POWER_OFF_CHARGING_LEVEL_1)
        return 0;

    if(bat_sta < POWER_OFF_CHARGING_LEVEL_2)
        return 1;

    if(bat_sta < POWER_OFF_CHARGING_LEVEL_3)
        return 2;

    if(bat_sta < POWER_OFF_CHARGING_LEVEL_4)
        return 3;

    return 0;
}

static void power_off_charging_battery_task(lv_task_t * task)
{
    uint8_t bat_sta = Hal_Battery_Get_Status();
    power_off_charging_check_full(&bat_sta);

    if(100 < bat_sta) {
        printf("Error, battery exceeds 100!\n");
        return;
    }

    lv_power_off_charging_ext_t * ext = power_off_charging_get_ext();
    if(100 == bat_sta) {
        lv_obj_t * watch_obj = power_off_charging_get_obj();
        if(watch_obj != NULL) {
            lv_obj_t * img_ok = lv_img_create(watch_obj, NULL);
            lv_obj_set_size(img_ok, lv_obj_get_width(watch_obj), lv_obj_get_height(watch_obj));
            lv_img_set_src(img_ok, &ICON_POWER_OFF_CHARGING_OK);
        }

        if(NULL != ext->battery_task) {
            lv_task_del(ext->battery_task);
            ext->battery_task = NULL;
        }
    } else {
        uint8_t index = ext->display_index++;

        if(index == POWER_OFF_CHARGING_LEVEL_MAX) {
            ext->display_index = power_off_charging_get_img_index(bat_sta);

            for(index = ext->display_index; index < POWER_OFF_CHARGING_LEVEL_MAX; index++) {
                lv_obj_set_hidden(ext->bat_img_list[index], true);
            }

            return;
        }

        lv_obj_set_hidden(ext->bat_img_list[index], false);
    }
}

static void power_off_ril_check(lv_task_t * task)
{
    printf("%s\n", __FUNCTION__);

    if(!watch_modem_adp_get_ril_ready_state_req()) return;

    printf("%s perform power off\n", __FUNCTION__);

    lv_power_off_charging_ext_t * ext = power_off_charging_get_ext();

    Hal_Power_Off(HAL_TYPE_POWER_OFF);
    lv_task_set_period(ext->ril_check_task, 2000);
}

static void power_off_charging_status_change(void * para)
{
    uint32_t chg_status = (uint32_t)para;
    printf("%s: status=%d\n", __func__, chg_status);

    if(NULL == lv_watch_get_activity_obj(ACT_ID_POWER_OFF_CHARGING)) return;    // has powered on

    /* power off when USB is pulled out while charging */
    if(HAL_CHG_DISCONNECTED == (HAL_CHG_STATUS)chg_status) {
        watch_set_suspend_enable(false, ACT_ID_POWER_OFF_CHARGING, 0);
        watch_set_ready_state(false);
        Hal_Backlight_Off();
        lv_power_off_charging_ext_t * ext = power_off_charging_get_ext();
        power_off_charging_prepare_destory(NULL);
        if(NULL == ext->ril_check_task)
            ext->ril_check_task = lv_task_create(power_off_ril_check, 200, LV_TASK_PRIO_HIGH, NULL);
    }
}

static void power_off_charging_prepare_destory(lv_obj_t * activity_obj)
{
    lv_power_off_charging_ext_t * ext = power_off_charging_get_ext();

    if(NULL == ext) return;

    if(NULL != ext->battery_task) {
        lv_task_del(ext->battery_task);
        ext->battery_task = NULL;
    }

    lv_watch_png_cache_all_free();
}

/* for battery value filter */
static void power_off_charging_check_full(uint8_t * value)
{
    static uint8_t power_full_cnt = 0;

    if(*value == 100) {
        if(power_full_cnt < POWER_OFF_CHARGING_FULL_CNT_MAX) {
            power_full_cnt++;
            *value = 99;
        }
    }
}

#endif /*USE_LV_WATCH_POWER_OFF_CHARGING*/
